package com.wyl.spelAndAop.aop;

import com.wyl.spelAndAop.annotation.MyLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

/**
 * 参考博客：https://blog.csdn.net/weixin_45080497/article/details/129130514?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168117959416800227435599%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168117959416800227435599&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-129130514-null-null.142^v82^insert_down38,201^v4^add_ask,239^v2^insert_chatgpt&utm_term=spel%E8%A1%A8%E8%BE%BE%E5%BC%8F%E9%85%8D%E5%90%88%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B3%A8%E8%A7%A3%E8%A7%A3%E6%9E%90&spm=1018.2226.3001.4187
 * @author 吴宇亮 on 2023/4/11 10:40
 */
@Component // 加入到spring容器
@Aspect     //切面
public class MyLogAspect {

    /**
     * 方法用途（切入点表达式可以用&&,||,!来组合使用）:
     *      execution: 匹配连接点：execution(* com.example.demo.*(..))--com.example.demo包下所有类的方法
     *      within: 某个类里面
     *      this: 指定AOP代理类的类型
     *      target:指定目标对象的类型
     *      args: 指定参数的类型
     *      bean:指定特定的bean名称，可以使用通配符（Spring自带的）
     *      @target： 带有指定注解的类型
     *      @args: 指定运行时传的参数带有指定的注解
     *      @within: 匹配使用指定注解的类
     *      @annotation:指定方法所应用的注解
     * <br/>
     * 操作步骤: TODO<br/>
     * ${tags}
     */
    @Pointcut("@annotation(com.wyl.spelAndAop.annotation.MyLog)")
    public void asAnnotation() {}

    @Around("asAnnotation() && @annotation(annotationDemo)")
    public Object around(ProceedingJoinPoint joinPoint, MyLog annotationDemo) {
        Object result = null;
        try {
            result = joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        // 解析入参
        EvaluationContext evaluationContext=new StandardEvaluationContext();
        evaluationContext.setVariable("param" , joinPoint.getArgs());
        // 解析返回值
        evaluationContext.setVariable("result", result);

        SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
        // 解析url
        String urlExpression = annotationDemo.url();
        Expression expression = spelExpressionParser.parseExpression(urlExpression, ParserContext.TEMPLATE_EXPRESSION);
        String url = expression.getValue(evaluationContext, String.class);
        System.out.println(url);
        // 解析comment
        for (String commentExpression : annotationDemo.comments()) {
            expression = spelExpressionParser.parseExpression(commentExpression, ParserContext.TEMPLATE_EXPRESSION);
            String comment = expression.getValue(evaluationContext, String.class);
            System.out.println(comment);
        }
        return result;
    }
}
